#include <boost/asio.hpp>
#include <boost/asio/posix/stream_descriptor.hpp>
#include <sys/eventfd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/wait.h>
#include <unistd.h>
#include <iostream>
#include <thread>
#include <cstring>

/**
 * EventFD跨进程通信问题诊断工具
 * 
 * 这个工具用于验证：
 * 1. EventFD在进程间传递是否正常
 * 2. 不同进程中的EventFD文件描述符值
 * 3. 跨进程EventFD通知是否能正常工作
 */

using namespace boost::asio;

class EventFdHelper {
public:
    static int send_fd(int socket_fd, int fd_to_send) {
        std::cout << "[发送进程] 准备发送 fd=" << fd_to_send << " 通过socket=" << socket_fd << std::endl;
        
        struct msghdr msg;
        memset(&msg, 0, sizeof(msg));
        char buf[CMSG_SPACE(sizeof(fd_to_send))];
        memset(buf, '\0', sizeof(buf));
        
        struct iovec io = { .iov_base = (void*)"FD", .iov_len = 2 };
        msg.msg_iov = &io;
        msg.msg_iovlen = 1;
        
        msg.msg_control = buf;
        msg.msg_controllen = sizeof(buf);
        
        struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
        cmsg->cmsg_level = SOL_SOCKET;
        cmsg->cmsg_type = SCM_RIGHTS;
        cmsg->cmsg_len = CMSG_LEN(sizeof(fd_to_send));
        
        *((int*)CMSG_DATA(cmsg)) = fd_to_send;
        
        int result = sendmsg(socket_fd, &msg, 0);
        if (result > 0) {
            std::cout << "[发送进程] 成功发送 fd=" << fd_to_send << std::endl;
        } else {
            std::cout << "[发送进程] 发送失败, errno=" << errno << std::endl;
        }
        return result;
    }
    
    static int recv_fd(int socket_fd) {
        std::cout << "[接收进程] 准备从 socket=" << socket_fd << " 接收fd" << std::endl;
        
        struct msghdr msg = {0};
        char m_buffer[256];
        char c_buffer[256];
        
        struct iovec io = { .iov_base = m_buffer, .iov_len = sizeof(m_buffer) };
        msg.msg_iov = &io;
        msg.msg_iovlen = 1;
        msg.msg_control = c_buffer;
        msg.msg_controllen = sizeof(c_buffer);
        
        if (recvmsg(socket_fd, &msg, 0) < 0) {
            std::cout << "[接收进程] recvmsg失败, errno=" << errno << std::endl;
            return -1;
        }
        
        struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
        if (cmsg && cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
            int received_fd = *((int*)CMSG_DATA(cmsg));
            std::cout << "[接收进程] 成功接收 fd=" << received_fd << std::endl;
            return received_fd;
        }
        
        std::cout << "[接收进程] 未收到有效的文件描述符" << std::endl;
        return -1;
    }
};

void test_eventfd_cross_process() {
    std::cout << "\n=== EventFD跨进程通信诊断 ===" << std::endl;
    
    // 创建socketpair用于进程间通信
    int sv[2];
    if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1) {
        perror("socketpair");
        return;
    }
    
    pid_t pid = fork();
    if (pid == -1) {
        perror("fork");
        return;
    }
    
    if (pid == 0) {
        // 子进程 - 模拟订阅者
        close(sv[0]);
        std::cout << "\n[子进程] 订阅者进程启动, PID=" << getpid() << std::endl;
        
        // 接收eventfd
        int received_eventfd = EventFdHelper::recv_fd(sv[1]);
        if (received_eventfd == -1) {
            std::cout << "[子进程] 接收EventFD失败" << std::endl;
            exit(1);
        }
        
        std::cout << "[子进程] 接收到EventFD, 本进程中fd值=" << received_eventfd << std::endl;
        
        // 设置异步监听
        io_context io;
        posix::stream_descriptor descriptor(io, received_eventfd);
        
        std::cout << "[子进程] 开始异步监听EventFD事件..." << std::endl;
        
        // 异步读取eventfd
        auto buffer = std::make_shared<uint64_t>();
        std::function<void()> async_read = [&]() {
            descriptor.async_read_some(
                boost::asio::buffer(buffer.get(), sizeof(*buffer)),
                [&, buffer](const boost::system::error_code& ec, std::size_t bytes) {
                    if (!ec) {
                        std::cout << "[子进程] 收到EventFD通知! 值=" << *buffer 
                                  << ", 字节数=" << bytes << std::endl;
                        // 继续监听
                        async_read();
                    } else {
                        std::cout << "[子进程] EventFD读取错误: " << ec.message() << std::endl;
                    }
                }
            );
        };
        
        async_read();
        
        // 通知父进程准备完成
        char ready = 'R';
        send(sv[1], &ready, 1, 0);
        
        // 运行IO循环，等待事件
        std::thread io_thread([&io]() {
            std::cout << "[子进程] IO循环开始运行..." << std::endl;
            io.run();
            std::cout << "[子进程] IO循环结束" << std::endl;
        });
        
        // 等待10秒后超时
        sleep(10);
        std::cout << "[子进程] 超时，停止监听" << std::endl;
        io.stop();
        
        if (io_thread.joinable()) {
            io_thread.join();
        }
        
        close(sv[1]);
        exit(0);
        
    } else {
        // 父进程 - 模拟发布者/注册中心
        close(sv[1]);
        std::cout << "\n[父进程] 发布者进程启动, PID=" << getpid() << std::endl;
        
        // 创建eventfd
        int original_eventfd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
        if (original_eventfd == -1) {
            perror("eventfd");
            return;
        }
        
        std::cout << "[父进程] 创建EventFD, 本进程中fd值=" << original_eventfd << std::endl;
        
        // 发送eventfd给子进程
        if (EventFdHelper::send_fd(sv[0], original_eventfd) <= 0) {
            std::cout << "[父进程] 发送EventFD失败" << std::endl;
            return;
        }
        
        // 等待子进程准备完成
        char ready;
        recv(sv[0], &ready, 1, 0);
        std::cout << "[父进程] 子进程准备完成，开始发送测试消息" << std::endl;
        
        // 发送多个测试消息
        for (int i = 1; i <= 5; i++) {
            sleep(1);  // 间隔1秒
            
            uint64_t notification = i;
            ssize_t result = write(original_eventfd, &notification, sizeof(notification));
            
            if (result == sizeof(notification)) {
                std::cout << "[父进程] 发送通知 #" << i << ", 值=" << notification 
                          << " 到eventfd=" << original_eventfd << std::endl;
            } else {
                std::cout << "[父进程] 发送通知 #" << i << " 失败, errno=" << errno << std::endl;
            }
        }
        
        std::cout << "[父进程] 所有测试消息发送完成，等待子进程..." << std::endl;
        
        // 等待子进程结束
        int status;
        wait(&status);
        
        close(original_eventfd);
        close(sv[0]);
        
        std::cout << "[父进程] 测试完成" << std::endl;
    }
}

int main() {
    std::cout << "EventFD跨进程通信问题诊断工具" << std::endl;
    std::cout << "================================" << std::endl;
    
    test_eventfd_cross_process();
    
    return 0;
}
